/*
 * @Author: crixusshen
 * @Date: 2021-06-03 08:17:41
 * @LastEditTime: 2021-06-03 09:09:42
 * @LastEditors: Please set LastEditors
 * @Description: taro scrollView Compatible
 */
import React, { Component } from "react";
import { ScrollView } from "@tarojs/components";
import omit from "lodash/omit";

type ElementOf<T> = T extends React.ComponentClass<infer E> ? E : never;
type ScrollViewProps = ElementOf<typeof ScrollView>;
export interface FScrollViewProps extends ScrollViewProps {
  // 用于后期属性二次扩展
}

function debounce (fn, delay: number) {
  let timer: NodeJS.Timeout

  return function (...arrs) {
    clearTimeout(timer)
    timer = setTimeout(function () {
      fn(...arrs)
    }, delay)
  }
}

export class FScrollView extends Component<FScrollViewProps> {
  // 临时存储应用层 onScroll 事件
  private _onScroll: Function = () => {}

  private _scrollLeft: number
  private _scrollTop: number

  // 构建一个 Ref 代理
  private el: HTMLElement

  private upperThreshold: number | string = 50
  private lowerThreshold: number | string = 50

  onMyScroll(e) {
    const {
      scrollLeft,
      scrollTop,
      scrollHeight,
      scrollWidth
    } = this.el;
    this._scrollLeft = scrollLeft
    this._scrollTop = scrollTop

    this.uperAndLower()

    if (this._onScroll) {
      this._onScroll({
        detail: {
          scrollLeft,
          scrollTop,
          scrollHeight,
          scrollWidth
        }
      })
    }
  }

  uperAndLower = debounce(() => {
    const {
      offsetWidth,
      offsetHeight,
      scrollLeft,
      scrollTop,
      scrollHeight,
      scrollWidth
    } = this.el

    const lowerThreshold = Number(this.lowerThreshold)
    const upperThreshold = Number(this.upperThreshold)

    if (
      !isNaN(lowerThreshold) &&
      ((this.props.scrollY && offsetHeight + scrollTop + lowerThreshold >= scrollHeight) ||
      (this.props.scrollX && offsetWidth + scrollLeft + lowerThreshold >= scrollWidth))
    ) {
      if(this.props.onScrollToLower) {
        this.props.onScrollToLower({
          detail: {
            scrollLeft,
            scrollTop,
            scrollHeight,
            scrollWidth
          }
        } as any)
      }
    }

    if (
      !isNaN(upperThreshold) &&
      ((this.props.scrollY && scrollTop <= upperThreshold) ||
      (this.props.scrollX && scrollLeft <= upperThreshold))
    ) {
      if(this.props.onScrollToUpper) {
        this.props.onScrollToUpper({
          detail: {
            scrollLeft,
            scrollTop,
            scrollHeight,
            scrollWidth
          }
        } as any)
      }
    }
  }, 200)

  render() {
    console.log("base layer render");
    const { onScroll, id } = this.props;
    if (onScroll) {
      this._onScroll = onScroll;
    }
    // 从原始数据中去除onScroll引用
    let otherProps = omit(this.props, ["onScroll"]);
    console.log(otherProps);
    return (
      <ScrollView
        ref={node => {
          this.el = node;
        }}
        {...otherProps}
        onScroll={this.onMyScroll.bind(this)}
      ></ScrollView>
    );
  }
}
